<template>
  <div class="home">
    <div class="home-banner">
      <i class="icon iconfont icon-ethereum"></i>
      <div class="action-row">
        <el-button round @click="initShowDialog(createInfo,'createUser')" circle title="创建账户"><span class="icon iconfont icon-add"></span></el-button>
        <el-button round @click="initShowDialog(importInfo,'importUser')" circle title="从私钥导入账户"><span class="icon iconfont icon-daoru"></span></el-button>
        <el-button round @click="initShowDialog(importInfoKeystore,'importUserKeystore')" circle title="从keystore导入账户"><span class="icon iconfont icon-daoru"></span></el-button>
      </div>
    </div>

    <div class="home-users-list">
      <template>
        <el-table
            :data="users"
            style="width: 100%">
          <el-table-column
              prop="username"
              label="账户名称"
              width="100">
          </el-table-column>
          <el-table-column
              prop="balance"
              label="ETH余额"
              width="150">
          </el-table-column>
          <el-table-column
              prop="address"
              label="address">
          </el-table-column>
          <el-table-column
              fixed="right"
              label="操作"
              width="100">
            <template slot-scope="scope">
              <el-button @click="viewAccount(scope.row)" type="text" size="small">查看</el-button>
              <el-button @click="exportKeystore(scope.row)" type="text" size="small">导出keystore</el-button>
              <el-button @click="deleteAccount(scope.row.id)" type="text" size="small">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </template>
    </div>

    <el-dialog
        title="创建账户"
        :visible.sync="dialogVisible.createUser">
      <div class="create-infos">
          <el-input v-model="createInfo.username" placeholder="仅保存本地作为标识">
            <template slot="prepend">账户名称</template>
          </el-input>
          <el-input v-model="createInfo.password" placeholder="密码" type="password">
            <template slot="prepend">设置密码</template>
          </el-input>
          <el-input v-model="createInfo.password_confirm" placeholder="确认密码" type="password">
            <template slot="prepend">确认密码</template>
          </el-input>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible.createUser = false">取消</el-button>
        <el-button type="primary" @click="createUser">创建</el-button>
      </span>
    </el-dialog>

    <el-dialog
        title="从私钥导入账户"
        :visible.sync="dialogVisible.importUser">
      <div class="create-infos">
        <el-input v-model="importInfo.username" placeholder="仅保存本地作为标识">
          <template slot="prepend">账户名称</template>
        </el-input>
        <el-input
            v-model="importInfo.privateKey"
            type="textarea"
            :autosize="{minRows: 2}"
            placeholder="请粘贴账户私钥">
        </el-input>
        <el-input v-model="importInfo.password" placeholder="密码" type="password">
          <template slot="prepend">设置密码</template>
        </el-input>
        <el-input v-model="importInfo.password_confirm" placeholder="确认密码" type="password">
          <template slot="prepend">确认密码</template>
        </el-input>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible.importUser = false">取消</el-button>
        <el-button type="primary" @click="importUserFromPrivate">导入</el-button>
      </span>
    </el-dialog>

    <el-dialog
        @close="clearKeystoreFiles"
        title="从 keystore 导入账户"
        :visible.sync="dialogVisible.importUserKeystore">
      <div class="create-infos">
        <el-input v-model="importInfoKeystore.username" placeholder="仅保存本地作为标识">
          <template slot="prepend">账户名称</template>
        </el-input>

        <el-upload
            ref="keystore_uploader"
            action=""
            :auto-upload="false"
            class="keystore-uploader"
            drag
            :limit="1"
            :on-change="uploadKeystore">
          <i class="el-icon-upload"></i>
          <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        </el-upload>

        <el-input v-model="importInfoKeystore.password" placeholder="请输入keystore的加密密码" type="password">
          <template slot="prepend">输入密码</template>
        </el-input>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible.importUserKeystore = false">取消</el-button>
        <el-button type="primary" @click="importUserFromKeystore">导入</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
  import Vue from 'vue'
  import {getLowDB, getNowTime} from '../assets/js/util.js'

  let db = getLowDB()
  db.defaults({
    users: [],
    users_count: 0,
    trans_logs: []
  }).write()

export default {
  data () {
    return {
      dialogVisible: {
        createUser: false,
        importUser: false,
        importUserKeystore: false
      },
      createInfo: {
        username: '',
        password: '',
        password_confirm: '',
      },
      importInfo: {
        username: '',
        privateKey: '',
        password: '',
        password_confirm: '',
      },
      importInfoKeystore: {
        keystoreStringFromFile: '',
        username: '',
        password: '',
      },
      users: []
    }
  },
  activated () {
    // activated: keep-alive 再次打开时刷新内容
    this.reloadUsers()
  },
  methods: {
    /**
     * 初始化创建/导入对话框
     * @param userAction 示例 createInfo
     * @param dialogToShow 示例 'createUser'
     */
    initShowDialog (userAction,dialogToShow) {
      for (let i in userAction) {
        userAction[i]=''
      }

      let count = Number(db.get('users_count').value())
      userAction.username = '账户'+(count+1)


      this.dialogVisible[dialogToShow] = true

    },
    // 创建用户
    createUser () {
      let createInfo = this.createInfo

      if (!this.checkInput(createInfo)) {
        return
      }

      if (createInfo.password.length < 8) {
        this.$message.error('输入一个强密码,至少8位')
        return false
      }

      try {
        // 创建账户
        let account = this.$web3.eth.accounts.create()

        // keystore存储
        let keystore = this.$web3.eth.accounts.encrypt(account.privateKey, createInfo.password)
        console.log('账户创建成功！', account)
        console.log('创建信息：', createInfo)
        console.log('keystore：', keystore)


        let new_id = null;
        db.update('users_count', (n) => {
          new_id = n + 1
          return new_id
        }).write()

        db.get('users').push({
          id: new_id,
          username: createInfo.username,
          password: createInfo.password,
          address: account.address,
          privateKey: account.privateKey,
          keystore: keystore
        }).write()

        this.$notify({
          message: `${createInfo.username}创建成功！`,
          type: 'success',
          offset: 50
        });

        this.reloadUsers()
        this.dialogVisible.createUser = false

      } catch (e) {
        console.error('账户创建失败', e)
        this.$message.error('账户创建失败')
      }


    },
    // 从私钥导入用户
    importUserFromPrivate () {
      let importInfo = this.importInfo

      if (importInfo.privateKey.indexOf('0x') !== 0) {
        this.$message.error('私钥格式错误')
        return
      }

      if (!this.checkInput(importInfo)) {
        return
      }

      let account = null
      try {
        account = this.$web3.eth.accounts.privateKeyToAccount(importInfo.privateKey)
        let keystore = this.$web3.eth.accounts.encrypt(importInfo.privateKey, importInfo.password)

        let new_id = null;
        db.update('users_count', (n) => {
          new_id = n + 1
          return new_id
        }).write()

        db.get('users').push({
          id: new_id,
          username: importInfo.username,
          password: importInfo.password,
          address: account.address,
          privateKey: account.privateKey,
          keystore: keystore
        }).write()

        this.$notify({
          message: `${importInfo.username}导入成功！`,
          type: 'success',
          offset: 50
        });

        this.reloadUsers()
        this.dialogVisible.importUser = false
      } catch (e) {
        console.error('私钥导入出错', e)
        this.$message.error('导入出错')
      }

    },
    // 上传keystore到内存
    uploadKeystore (file) {
      let self = this

      console.log('uploadKeystore', file)
      let fileSizeKB = file.size/1024
      if (fileSizeKB > 50) {
        this.$message.error('keystore文件尺寸不能大于50KB')
        return
      }

      let reader = new FileReader()

      reader.readAsText(file.raw)

      reader.onload = function(evt) {
        console.log('文件读取成功', evt)
        self.importInfoKeystore.keystoreStringFromFile = evt.target.result
      }
      reader.onerror = function(evt) {
        console.log('文件读取失败', evt)
        this.message.error('文件读取失败')
      }
    },
    clearKeystoreFiles() {
      this.$refs.keystore_uploader.clearFiles()
    },
    // 从keystore导入用户
    importUserFromKeystore () {
      let importInfo = this.importInfoKeystore

      if (!this.checkInput(importInfo)) {
        return
      }

      try {
        let keystore = JSON.parse(importInfo.keystoreStringFromFile)

        console.log(keystore, importInfo.password)

        let account = this.$web3.eth.accounts.decrypt(keystore, importInfo.password)

        let new_id = null;
        db.update('users_count', (n) => {
          new_id = n + 1
          return new_id
        }).write()

        db.get('users').push({
          id: new_id,
          username: importInfo.username,
          password: importInfo.password,
          address: account.address,
          privateKey: account.privateKey,
          keystore: keystore
        }).write()

        this.$notify({
          message: `${importInfo.username}导入成功！`,
          type: 'success',
          offset: 50
        });

        this.reloadUsers()
        this.dialogVisible.importUserKeystore = false
      } catch (e) {
        console.error('keystore导入出错', e)
        this.$message.error('账户导入失败，可能是密码错误')
      }
    },
    // 检查用户输入框
    checkInput (info) {
      for (let i in info) {
        if (info[i].length <= 0) {
          this.$message.error({
            message: i+'不能为空 或状态不正确',
            duration: 2000
          })
          return false
        }
      }

      if (typeof info.password_confirm !== 'undefined') {
        if (info.password !== info.password_confirm) {
          this.$message.error('两次输入的密码不一致')
          return false
        }
      }


      return true
    },
    // 刷新用户列表
    reloadUsers () {
      this.users = db.get('users').value()
      let self = this

      // 将金额单位Wei转换成Eth
      function _toEthVal (val){
        return self.$web3.utils.fromWei(val, 'ether');
      }

      // 获取余额
      function _getBalance(item) {
        self.$web3.eth.getBalance(item.address).then(data => {
          Vue.set(item, 'balance', _toEthVal(data))
        })
      }

      this.users.forEach(item => {
        _getBalance(item)
      })

      // 让Vue数组强制更新
      this.users = this.users.slice()

      // console.log('reloadUsers', this.users)
    },
    // 查看用户
    viewAccount (user) {
      this.$message('请打开控制台查看输出。')
      let tempObj = {}
      Object.assign(tempObj, user)

      console.log('账户信息', tempObj)
    },
    // 删除账户
    deleteAccount (id) {
      this.$confirm('此操作将永久删除该用户 id='+id+', 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        db.get('users').remove({ id }).write()
        this.reloadUsers()

        this.$message({
          type: 'success',
          message: '删除成功!'
        });
      }).catch(() => {
        // 取消操作
      });
    },
    // 导出keystore
    exportKeystore (user) {
      // 创建下载链接
      let link = document.createElement('a')
      link.download = getNowTime()+'--'+user.address
      link.style.display = 'none'
      // 创建下载内容
      let blob = new Blob([JSON.stringify(user.keystore)])
      link.href = URL.createObjectURL(blob)
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    }
  }
}
</script>

<style lang="stylus" scoped>
  .home
    background aliceblue
    .home-banner
      display flex
      justify-content center
      align-items center
      flex-direction column
      color: #fff
      min-height 220px
      background linear-gradient(45deg, #2d2b5d 0%, #4d4d8f 50%, #5a59a0 100%);
      .icon-ethereum
        font-size 100px
        margin-bottom: 20px
        &:hover
          animation rotateY 3s infinite linear
          animation-delay 3s
  .el-table .cell
    .el-button+.el-button
      margin-left: 0

  .el-dialog .text,
  .el-dialog .el-textarea,
  .el-dialog .el-alert,
  .el-dialog .el-input,
  .el-dialog .text,
  .keystore-uploader {margin-bottom: 10px;}
  @media only screen and (max-width: 425px) {
    >>>.el-dialog {
      width 100%
    }
  }

  @keyframes rotateY {
    0% {
      transform rotateY(0)
    }
    50% {
      transform rotateY(180deg)
    }
    100% {
      transform rotateY(0)
    }
  }
</style>